package com.example.config.handler.login.username;

import com.example.config.handler.login.ClientUserDetails;
import com.example.exception.BaseException;
import com.example.service.CaptchaService;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

/**
 * 帐号密码登录认证
 */
@Component
public class UsernameAuthenticationProvider implements AuthenticationProvider {

  @Autowired
  private UserService userService;

  @Autowired
  private PasswordEncoder passwordEncoder;

  @Autowired
  private CaptchaService captchaService;

  public UsernameAuthenticationProvider() {
    super();
  }

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    if (!(authentication instanceof UsernameAuthentication)) {
      return null; // 不支持的 token 类型
    }

    UsernameAuthentication usernameAuthentication = (UsernameAuthentication) authentication;


    String captcha = usernameAuthentication.getCaptcha();
    String uuid = usernameAuthentication.getUuid();
    if (!captchaService.validate(uuid, captcha)) {
      throw new BaseException("验证码不正确");
    }

    // 查数据库，匹配用户信息
    ClientUserDetails clientUserDetails = userService.getUserFromDB(usernameAuthentication.getUsername());

    if (clientUserDetails == null || !passwordEncoder.matches(usernameAuthentication.getPassword(), clientUserDetails.getPassword())) {
      throw new BadCredentialsException("${invalid.username.or.pwd:用户名或密码不正确}");
    }

    UsernameAuthentication token = new UsernameAuthentication(clientUserDetails.getAuthorities());
    token.setCurrentUser(clientUserDetails);
    token.setAuthenticated(true); // 认证通过，这里一定要设成true
    return token;
  }

  @Override
  public boolean supports(Class<?> authentication) {
    return authentication.isAssignableFrom(UsernameAuthentication.class);
  }
}

